package br.com.fogas.database.dao.impl;

import java.sql.SQLException;
import java.util.List;

import br.com.fogas.database.FogasDatabase;
import br.com.fogas.database.IMetadata;
import br.com.fogas.database.dao.INotaFiscalDao;
import br.com.fogas.database.entidade.Medidor;
import br.com.fogas.database.entidade.NotaFiscal;
import br.com.fogas.database.entidade.NotaItem;
import br.com.fogas.database.entidade.NotaItemCondicoes;
import br.com.fogas.database.entidade.NotaOcorrencia;
import br.com.fogas.database.entidade.PlanoVisitas;
import br.com.fogas.database.enums.PlanoVisitaStatusEnum;
import br.com.fogas.database.enums.StatusNotaEnum;

import com.j256.ormlite.dao.BaseDaoImpl;
import com.j256.ormlite.dao.ForeignCollection;

public class NotaFiscalDao extends BaseDaoImpl<NotaFiscal, Integer> implements INotaFiscalDao {
	
	private FogasDatabase database;

	public NotaFiscalDao(FogasDatabase database) throws SQLException {
		super(database.getConnectionSource(), NotaFiscal.class);
		this.database = database;
	}

	@Override
	public void limparSimulacoes() throws SQLException {
		List<NotaFiscal> simulacoes = queryBuilder().where()
				.eq(IMetadata.INotaFiscal.cs_simulacao, true)
				.query();
		apagarSimulacaoNotaFiscal(simulacoes);
	}
	
	private void apagarSimulacaoNotaFiscal(List<NotaFiscal> simulacoes) throws SQLException {
		for (NotaFiscal notaFiscal : simulacoes) {
			apagarSimulacaoNotaItem(notaFiscal.getNotaItems());
			database.getNotaFiscal().delete(notaFiscal);
		}
	}
	
	private void apagarSimulacaoNotaItem(ForeignCollection<NotaItem> notaItems) throws SQLException {
		for (NotaItem notaItem : notaItems) {
			apagarSimulacaoNotaItemCondicoes(notaItem.getItemCondicoes());
			database.getNotaItem().delete(notaItem);
		}
	}
	
	private void apagarSimulacaoNotaItemCondicoes(ForeignCollection<NotaItemCondicoes> notaItemCondicoes) throws SQLException {
		for (NotaItemCondicoes condicao : notaItemCondicoes) {
			database.getNotaCondicoes().delete(condicao);
		}
	}

	@Override
	public NotaFiscal gravarSimulacao(NotaFiscal notaFiscal) throws SQLException {
		atualizarMedidorLido(notaFiscal.getTx_medidor());
		
		database.getNotaFiscal().create(notaFiscal);
		
		for(NotaItem notaItem: notaFiscal.getNotaItemsTemp()) {
			database.getNotaItem().create(notaItem);
			
			for (NotaItemCondicoes condicao : notaItem.getItemCondicoesTemp()) {
				database.getNotaCondicoes().create(condicao);
			}
		}
		
		return notaPorSerieNumero(notaFiscal.getTx_serie(), notaFiscal.getTx_nfnum());
	}
	
	private void atualizarMedidorLido(Medidor medidor) throws SQLException {
		database.getMedidor().update(medidor);
	}

	@Override
	public NotaFiscal gravarNotaContigencia(NotaFiscal notaFiscal) throws SQLException {
		limparSimulacoes();
		
		database.getNotaFiscal().create(notaFiscal);
		
		for(NotaItem notaItem: notaFiscal.getNotaItemsTemp()) {
			database.getNotaItem().create(notaItem);
			
			for (NotaItemCondicoes condicao : notaItem.getItemCondicoesTemp()) {
				database.getNotaCondicoes().create(condicao);
			}
		}
		
		//atualiza a ocorrencia
		NotaOcorrencia notaOcorrencia = database.getNotaOcorrencia().queryForId(notaFiscal.getNotaOcorrencia().getId());
		notaOcorrencia.setTx_nota_fiscal(notaFiscal);
		database.getNotaOcorrencia().update(notaOcorrencia);
		
		return notaPorSerieNumero(notaFiscal.getTx_serie(), notaFiscal.getTx_nfnum());
	}

	@Override
	public NotaFiscal notaPorSerieNumero(String serie, String numero)
			throws SQLException {
		 List<NotaFiscal> notas = queryBuilder().where()
		 .eq(IMetadata.INotaFiscal.tx_serie, serie)
		 .and().eq(IMetadata.INotaFiscal.tx_nfnum, numero)
		 .query();
		 
		 if(notas != null && !notas.isEmpty()) {
			 return notas.get(0);
		 } else {
			 return null;
		 }
	}

	@Override
	public void cancelarNotaPorPlano(PlanoVisitas planoVisitas)
			throws SQLException {
		List<NotaFiscal> notas = queryBuilder().where()
				 .eq(IMetadata.INotaFiscal.tx_plano_visitas, planoVisitas)
				 .and().eq(IMetadata.INotaFiscal.cs_cancelada, false)
				 .query();
		
		NotaFiscal notaFiscal = notas.get(0);
		notaFiscal.setCs_cancelada(true);
		notaFiscal.setNb_sync(StatusNotaEnum.PENDENTE.getId());
		database.getNotaFiscal().update(notaFiscal);
		
		planoVisitas.setStatus(PlanoVisitaStatusEnum.PENDENTE.getId());
		database.getPlanoVisitas().update(planoVisitas);
	}
}
